In a pipelined processor, multiple pieces of data, such as instructions, can move simultaneously through the channel connecting the processor with a storage means. A storage controller is used to direct such data between the storage means and the processor through the storage channel. The data moving through the channel is tagged so as to identify its destination in the processor. Since the operation of the processor is much faster than that of the storage means, the use of such a pipelined storage channel together with appropriate buffers within the processor permits the processor to operate at its most effective rate and to conduct a plurality of simultaneous storage transactions. The concept of a pipelined storage channel is described in IBM Technical Disclosure Bulletin article, "Synchronous LSSD Packet Switching Memory and I/O Channel", published March 1982, pages 4986-4987 by Jeremiah et at, and in IBM Technical Disclosure Bulletin article, "Exact Interrupt Capability for Processors Using a Packet-Switching Storage Channel", published August 1982, pages 1771-1772 by Hester et al.
Instructions in such a pipelined processor are usually fetched several cycles in advance of their execution. This increases processor performance by allowing instruction accessing to be overlapped with instruction execution. A problem arises, however, whenever a successful branch instruction is encountered. A successful branch invalidates all instructions which have been prefetched since they are part of an old instruction stream. During the time that the processor is waiting to access the new instruction stream for the branch, it is essentially idle. This idle time decreases the overall performance of the processor.
A further problem that arises as a result of a branch is that the instruction prefetch buffer in the processor has no advance knowledge of a successful branch, so there may be several pending requests from previous prefetches when the successful branch occurs. The problem then is how to distinguish between old prefetches, i.e., ones that occurred before the successful branch and which are no longer necessary, and the new prefetches which are needed as a result of the successful branch.
One approach to solve this branching problem is to divide the instruction prefetch buffer into two halves, and to alternate between the two halves every time a successful branch occurs. Since the storage channel utilizes a tag to identify each request source, a set of tags could be associated with each half of the instruction prefetch buffer. Thus, whenever a successful branch occurs, the instruction prefetch buffer would change to the alternate set of tags. In this manner, the instruction prefetch buffer could determined whether or not a reply from a prefetch request should go into the active half of the buffer by comparing the returned tag with the currently active tag set. If the tag were a member of the active set, then the prefetch would be associated with the current execution stream and consequently should be place in the active half of the buffer. Conversely, if the tag were not a member of the active set, then it would no loner be required and could be placed in the inactive half of the buffer. Although this approach is workable, it only utilizes one-half of the storage area in the instruction prefetch buffer at any given time.
One technique for overcoming the branching problem is disclosed in U.S. Pat. No. 4,430,706, wherein a branch prediction approach is employed. In this approach, an auxiliary implementation is added to a pipelined data processor for monitoring both the instruction flow and the recent conditional branches and their outcome. Whenever a branch instruction is encountered more than once, its prior behavior is used to predict the particular branch to be taken. The processor then provisionally executes the instructions in such predicted branch. However, when a predicted branch turns out to be incorrect, such processing ceases and the processor then attempts to take a correct branch. Two problems with this approach are that, first, extra hardware is required, and second, processing time is wasted whenever a wrong branch is predicted and subsequently processed.
Another approach to the branching problem is disclosed in U.S. Pat. Nos. 4,155,120 and 4,179,737, wherein it is assumed that no branching possibilities are present. In accordance with this approach, microinstruction sequencing is assumed to be unconditional even though a plurality of branching possibilities may indeed exist in the microinstruction sequencing flow. In this manner, microinstruction sequencing may proceed rapidly as long as no branching occurs. However, when a branch does in fact occur, it must be detected and then a correction cycle must be initiated. A problem with this approach is that as the number of branching operations increases, sequencing must be altered and corrected for incorrect sequencing because of lack of recognition of branching possibilities. Further this approach requires means for monitoring the correctness of the sequencing of microinstructions concurrently with the execution of microinstructions during each cycle for which a branching decision is required.
Still another approach to reducing performance degradation due to branching is to introduce a set of branch-with-execute, also known as delayed branch, instructions. These instructions are defined such that the next sequential instruction following the branch instruction is executed prior to he execution of the branch target instruction. This next sequential instruction is known as the subject instruction. The subject instruction usually has already been fetched at the completing of the branch-with-execute instruction, and consequently, the processor executes it instead of remaining idle while waiting for the branch target fetch to be completed.
The branch-with-execute approach is relatively easy to implement on a processor which has a single instruction prefetch buffer. The processor executes the subject instruction which is being fetched and decoded while the branch-with-execute instruction is executing. In a normal branch, the processor would ignore the subject instruction. However, the branch-with-execute approach becomes much more difficult to implement as the size of the instruction prefetch buffer increases.